#include <core/types.h>
#include <stdio.h>
#include <core/errno.h>
#include <string.h>


static int HexStrToVal(const char *pStr, ULONG *pVal)
{
#define MAX_HEX_STR_LEN (sizeof(ULONG) * 2)
	ULONG ulVal = 0;
	int nLen = 0;

	while (*pStr != '\0')
	{
		if (!ISHEX(*pStr))
			return  -EINVAL;

		nLen++;
		if (nLen > MAX_HEX_STR_LEN)
			return -EINVAL;

		if (*pStr >= '0' && *pStr <= '9')
		{
			ulVal <<= 4;
			ulVal |= *pStr - '0';
		}
		else if (*pStr >= 'a' && *pStr <= 'f')
		{
			ulVal <<= 4;
			ulVal |= *pStr - 'a' + 10;
		}
		else if (*pStr >= 'A' && *pStr <= 'F') 
		{
			ulVal <<= 4;
			ulVal |= *pStr - 'A' + 10;
		}

		pStr++;
	}

	*pVal = ulVal;

	return nLen;
}


// "3G40M512K256"
static int HrStrToVal(const char *pStr, ULONG *pulNum)
{
	BYTE  cMark = 0;
	ULONG ulNum = 0, ulTmp = 0;

	while (1)
	{
		switch (*pStr)
		{
		case '\0':			
			ulNum  += ulTmp;
			*pulNum = ulNum;
			return 0;

		case '0' ... '9':
			ulTmp = ulTmp * 10 + *pStr - '0';
			break;

		case 'g':
		case 'G':
			if (cMark & (1 << 7 | 1 << 6 | 1 << 5))
			{
				goto error;
			}

			ulNum += ulTmp << 30;
			ulTmp = 0;

			cMark |= 1 << 7;

			break;

		case 'm':
		case 'M':
			if (cMark & (1 << 6 | 1 << 5))
			{
				goto error;
			}

			ulNum += ulTmp << 20;
			ulTmp = 0;

			cMark |= 1 << 6;

			break;

		case 'k':
		case 'K':
			if (cMark & (1 << 5))
			{
				goto error;
			}

			ulNum += ulTmp << 10;
			ulTmp = 0;

			cMark |= 1 << 5;

			break;

		default:
			goto error;
		}

		pStr++;
	}

error:
	return -EINVAL;
}


int GuStrToVal(const char *pStr, ULONG *pVal)
{
#if 1
	int ret;
	ULONG ulTmp;

	if ('0' == *pStr && ('x' == *(pStr + 1) || 'X' == *(pStr + 1)))
	{
		ret = HexStrToVal(pStr + 2, &ulTmp);
	}
	else if ('0' == *pStr)
	{
		// fixme
	}
	else
	{
		ret = HrStrToVal(pStr, &ulTmp);
	}

	if (ret >= 0)
	{
		*pVal = ulTmp;
	}

	return ret;
#else
	if ('0' == *pStr && ('x' == *(pStr + 1) || 'X' == *(pStr + 1)))
		return HexStrToVal(pStr + 2, pVal);

	if ('0' == *pStr)
	{
		// fixme
	}

	return HrStrToVal(pStr, pVal);
#endif
}


#define KB_MASK ((1 << 10) - 1)

// testing:
int GuValToHrStr(ULONG ulVal, char pStr[])
{
	char *p;
	ULONG ulSect;


	p = pStr;

	if (ulSect = (ulVal >> 30) & KB_MASK)
		p += sprintf(p, "%dG", ulSect);

	if (ulSect = (ulVal >> 20) & KB_MASK)
		p += sprintf(p, "%dM", ulSect);

	if (ulSect = (ulVal >> 10) & KB_MASK)
		p += sprintf(p, "%dK", ulSect);

	if (ulSect = ulVal & KB_MASK)
		p += sprintf(p, "%dB", ulSect);
	else if (p == pStr)
		strcpy(pStr, "0B");

	return 0;
}


int GuStrToIp(BYTE vbIP[4], const char *pStr)
{
	int i = 0;

	vbIP[0] = 0;

	while (*pStr)
	{
		if ('.' == *pStr)
		{
			i++;
			if (4 == i)
				return -EINVAL;

			vbIP[i] = 0;
		}
		else
		{
			vbIP[i] = vbIP[i] * 10 + *pStr - '0';
		}

		pStr++;
	}

	return 0;
}



int GuIpToStr(char szBuf[], const UINT32 dwIpAddr)
{
	sprintf(szBuf, "%d.%d.%d.%d",
			dwIpAddr & 0xff,
			(dwIpAddr >> 8) & 0xff,
			(dwIpAddr >> 16) & 0xff,
			(dwIpAddr>> 24) & 0xff);

	return 0;
}


